﻿using System.Data.Entity;
using Microsoft.Practices.Unity;
using MiniStock.BusinessLogic.EntityPersister;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Linq;
using MiniStock.BusinessLogic.EventQueue.Data;
using MiniStock.BusinessLogic.EventQueue.Queue;
using MiniStock.Database;
using MiniStock.Entities.Common;
using MiniStock.Entities.Common.Events;
using MiniStock.Entities.Stock;
using MiniStock.Entities.Stock.Events;
using MiniStock.Entities.Stock.Events.Customer;
using MiniStock.Infrastructure;
using MiniStock.Infrastructure.Configurator;
using MiniStock.Infrastructure.Implementation;
using MiniStock.Infrastructure.Queue;

namespace MiniStock.BusinessLogic.EntityPersister.Test
{
    
    
    /// <summary>
    ///This is a test class for EventPersisterWorkerTest and is intended
    ///to contain all EventPersisterWorkerTest Unit Tests
    ///</summary>
    [TestClass()]
    public class EntityPersisterWorkerTest
    {
        public static IUnityContainer RootContainer;

        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        [ClassInitialize()]
        public static void MyClassInitialize(TestContext testContext)
        {
            IProcessorPluginEntryPoint pep = new PluginEntryPoint();

            SerializationHelper.KnownEntityTypes.Clear();
            SerializationHelper.KnownEventTypes.Clear();

            SerializationHelper.RegisterKnownEventTypes(pep.EventRootTypes);
            SerializationHelper.RegisterKnownEntityTypes(pep.EntityRootTypes);

            EventBaseExtender.InitSerializer();
            EntityBaseExtender.InitSerializer();
        }

        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        [TestInitialize()]
        public void MyTestInitialize()
        {
            RootContainer = new UnityContainer();
            RootContainer.RegisterType<IEventQueue, MemoryQueue>(new ContainerControlledLifetimeManager());
            RootContainer.RegisterType<IEventQueue, MemoryQueue>("InternalQueue", new ContainerControlledLifetimeManager());

            var db = new EntityDbContext();
            db.Database.ExecuteSqlCommand("delete from OrderItems");
            db.Database.ExecuteSqlCommand("delete from Orders");
            db.Database.ExecuteSqlCommand("delete from Products");
            db.Database.ExecuteSqlCommand("delete from Customers");
        }
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        public Guid[] CustomerIdList = new[]{
                                               Guid.NewGuid(),
                                               Guid.NewGuid(),
                                           };


        /// <summary>
        ///A test for CustomerEventProcessor Constructor
        ///</summary>
        [TestMethod()]
        public void EventPersisterWorkerTest_CreateCustomerEvent()
        {
            EntityPersisterWorker sut = RootContainer.Resolve<EntityPersisterWorker>();
            sut.InputEventQueue.Configure(new TestQueueConfigurator(), Guid.NewGuid().ToString());
            sut.OutputEventQueue = RootContainer.Resolve<IEventQueue>();
            sut.OutputEventQueue.Configure(new TestQueueConfigurator(), "out");
            var customerId = CustomerIdList[0];
            EntityBase customer;

            sut.AddEvent(new MessagePersistedEvent
            {
                EventId = Guid.NewGuid(),
                EventDate = DateTime.Now,
                CorrelatedEventId = Guid.NewGuid(),
                Entity = new Customer() {
                    Id = customerId,
                    Name = "Teszt Pista",
                    ContactPerson = new ContactPerson() {},
                    HQAddress = new Address() {},
                    ShippingAddress = new Address() {},
                },
                //SubmittedBy = Guid.NewGuid().ToString(),
            });

            Assert.AreEqual(1, sut.GetQueueSize());
            Assert.AreEqual("Customer|" + customerId, sut.GetEntityIdList().Distinct().Single());

            customer = sut.DbContext.GetEntityByHash("Customer|" + customerId.ToString());
            Assert.IsNull(customer);
            var result = sut.DoWork();
            Assert.AreEqual(true, result);
            customer = sut.DbContext.GetEntityByHash("Customer|" + customerId.ToString());
            Assert.IsNotNull(customer);
        }

        /// <summary>
        ///A test for CustomerEventProcessor Constructor
        ///</summary>
        //[TestMethod()]
        public void EventPersisterWorkerTest_ChangeCustomerNameEvent()
        {
            EntityPersisterWorker sut = RootContainer.Resolve<EntityPersisterWorker>();
            sut.InputEventQueue.Configure(new TestQueueConfigurator(), Guid.NewGuid().ToString());
            sut.OutputEventQueue = RootContainer.Resolve<IEventQueue>();
            sut.OutputEventQueue.Configure(new TestQueueConfigurator(), "out");
            var customerId = CustomerIdList[0];
            EntityBase customer;

            sut.AddEvent(new CreateCustomerEvent
            {
                EventId = Guid.NewGuid(),
                EventDate = DateTime.Now.AddSeconds(-1),
                Id = customerId,
                Name = "Teszt Pista",
                //SubmittedBy = Guid.NewGuid().ToString(),
            });

            sut.AddEvent(new ChangeCustomerNameEvent
            {
                EventId = Guid.NewGuid(),
                EventDate = DateTime.Now,
                Id = customerId,
                Name = "Teszt Józsi",
                //SubmittedBy = Guid.NewGuid().ToString(),
            });

            Assert.AreEqual(2, sut.GetQueueSize());
            Assert.AreEqual("Customer|" + customerId, sut.GetEntityIdList().Distinct().Single());

            customer = sut.DbContext.GetEntityByHash("Customer|" + customerId.ToString());
            Assert.IsNull(customer);
            var result = sut.DoWork();
            Assert.AreEqual(true, result);
            customer = sut.DbContext.GetEntityByHash("Customer|" + customerId.ToString());
            Assert.IsNotNull(customer);
            Assert.AreEqual("Teszt Pista", ((Customer)customer).Name);

            result = sut.DoWork();
            Assert.AreEqual(true, result);
            customer = sut.DbContext.GetEntityByHash("Customer|" + customerId.ToString());
            Assert.IsNotNull(customer);
            Assert.AreEqual("Teszt Józsi", ((Customer)customer).Name);
        }
    }
}
